﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint;
using SPContrib.Artifacts.Definitions;
using SPContrib.Extensions;

namespace SPContrib.Artifacts.Collections
{
    /// <summary>
    /// TODO: document
    /// </summary>
    public class ContentTypeDefinitionCollection : IEnumerable<ContentTypeDefinition>
    {
        private SPContentTypeCollection _ctypes;
        private List<ContentTypeDefinition> _definitions;
        private SPFieldCollection _sitecolumns;

        internal SPFieldCollection SiteColumns
        {
            get
            {
                return _sitecolumns;
            }
        }

        internal SPField FindSiteColumnByDefinition(FieldRefDefinition definition)
        {
            SPField match = _sitecolumns.TryGetFieldByStaticName(definition.Name);
            if (match == null)
            {
                throw "ContentTypeDefinitionCollection: method FindSiteColumnByDefinition failed to find a sitecolumn with id '{0}' at url '{1}'"
                        .AsException(definition.Id, _sitecolumns.Web.Url);
            }

            return match;
        }

        public ContentTypeDefinitionCollection(SPFeature feature)
        {
            switch (feature.Scope())
            {
                case SPFeatureScope.Site:
                case SPFeatureScope.Web:
                    EnsureContentTypeContext(feature.EnsureScope<SPWeb>(SPFeatureScope.Web));
                    break;
                default:
                    throw "ContentTypeCollection: invalid feature scope '{0}'. Allowed values are Site|Web"
                            .AsException(feature.Definition.Scope);
            }

            this._definitions = (from definition in feature.ElementDefinitions()
                                where definition.ElementType == "ContentType"
                                select new ContentTypeDefinition(this, definition))
                                .OrderByDescending(ctd => ctd.Id) // inheriting ones first
                                .ToList();
                                

        }

        public ContentTypeDefinitionCollection(SPSite sitecollection)
        {
            EnsureContentTypeContext(sitecollection.RootWeb);
        }

        public ContentTypeDefinitionCollection(SPWeb website)
        {
            EnsureContentTypeContext(website);
        }

        public ContentTypeDefinitionCollection(SPList list)
        {
            // TODO: implement
            throw new NotImplementedException();
        }

        private void EnsureContentTypeContext(SPWeb website)
        {
            this._ctypes = website.ContentTypes;
            this._sitecolumns = website.AvailableFields; // TODO: we cannot add to this collection
        }

        public void Synchronize()
        {
            foreach (ContentTypeDefinition definition in _definitions)
            {
                definition.Synchronize();
            }
        }

        internal SPContentType FindContentTypeByDefinition(ContentTypeDefinition contentTypeDefinition)
        {
            SPContentType result;
            bool match = _ctypes
                            .TryFindById(contentTypeDefinition.Id, out result);

            if (match == false)
            {
                throw "ContentTypeDefinitionCollection: could not find a content type with id '{0}'"
                        .AsException(contentTypeDefinition.Id);
            }

            return result;
        }

        //public ContentTypeDefinition this[SPContentTypeId id]
        //{
        //    get
        //    {
        //        return new ContentTypeDefinition(this, id);
        //    }
        //}


        //public ContentTypeDefinition this[string name]
        //{
        //    get
        //    {
        //        return new ContentTypeDefinition(this, name);
        //    }
        //}
        

        //internal SPContentType EnsureParentContentType(SPContentTypeId value)
        //{
        //    SPContentType instance;
        //    if (AvailableContentTypes.TryLocateContentType(value, out instance) == false)
        //    {
        //        throw "ContentTypeCollection: the content type with id '{0}' was not found. Inheritance failed."
        //                .AsException(value);
        //    }

        //    return instance;
        //}

        //internal SPContentType EnsureContentTypeInstance(ContentTypeDefinition definition)
        //{
        //    SPContentType instance = default(SPContentType);

        //    if (AllContentTypes.TryLocateContentType(definition.ContentTypeName, out instance) == false)
        //    {
        //        // add content type
        //        if (definition.UsesInheritance)
        //        {
        //            instance = AllContentTypes.Add(definition.ParentContentType, definition.ContentTypeName);
        //        }
        //        else
        //        {
        //            instance = AllContentTypes.Add(definition.ContentTypeId, definition.ContentTypeName);
        //        }
        //    }
        //    OnUpdated(this, EventArgs.Empty);
        //    return instance;
        //}


        public IEnumerator<ContentTypeDefinition> GetEnumerator()
        {
            return _definitions.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _definitions.GetEnumerator();
        }

    }
}
